{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Superdense Coding Kata\n",
    "\n",
    "**Superdense Coding** quantum kata is a series of exercises designed to get you familiar with programming in Q#.\n",
    "\n",
    "It covers the superdense coding protocol which allows us to transmit two bits of classical information by sending just one qubit using previously shared quantum entanglement.\n",
    "\n",
    " - A good description can be found in [the Wikipedia article](https://en.wikipedia.org/wiki/Superdense_coding).\n",
    " - A great interactive demonstration can be found [on the Wolfram Demonstrations Project](http://demonstrations.wolfram.com/SuperdenseCoding/).\n",
    " - Superdense coding protocol is described in Nielsen & Chuang, section 2.3 (pp. 97-98).\n",
    "\n",
    "Each task is wrapped in one operation preceded by the description of the task. Your goal is to fill in the blank (marked with `// ...` comment) with some Q# code that solves the task. To verify your answer, run the cell using Ctrl/⌘+Enter.\n",
    "\n",
    "Each task defines an operation that can be used in subsequent tasks to simplify implementations and build on existing code.  We split the superdense coding protocol into several steps, following the description in the [Wikipedia article](https://en.wikipedia.org/wiki/Superdense_coding):\n",
    "\n",
    "* Preparation (creating the entangled pair of qubits that are sent to Alice and Bob).\n",
    "* Encoding the message (Alice's task): Encoding the classical bits of the message into the state of Alice's qubit which then is sent to Bob.\n",
    "* Decoding the message (Bob's task): Using Bob's original qubit and the qubit he received from Alice to decode the classical message sent.\n",
    "* Finally, we compose those steps into the complete superdense coding protocol."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To begin, first prepare this notebook for execution (if you skip this step, you'll get \"Syntax does not match any known patterns\" error when you try to execute Q# code in the next cells):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%package Microsoft.Quantum.Katas::0.10.1911.1607"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> The package versions in the output of the cell above should always match. If you are running the Notebooks locally and the versions do not match, please install the IQ# version that matches the version of the `Microsoft.Quantum.Katas` package.\n",
    "> <details>\n",
    "> <summary><u>How to install the right IQ# version</u></summary>\n",
    "> For example, if the version of `Microsoft.Quantum.Katas` package above is 0.1.2.3, the installation steps are as follows:\n",
    ">\n",
    "> 1. Stop the kernel.\n",
    "> 2. Uninstall the existing version of IQ#:\n",
    ">        dotnet tool uninstall microsoft.quantum.iqsharp -g\n",
    "> 3. Install the matching version:\n",
    ">        dotnet tool install microsoft.quantum.iqsharp -g --version 0.1.2.3\n",
    "> 4. Reinstall the kernel:\n",
    ">        dotnet iqsharp install\n",
    "> 5. Restart the Notebook.\n",
    "> </details>\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Task 1. Entangled pair\n",
    "\n",
    "**Input:** Two qubits, each in the $|0\\rangle$ state.\n",
    "\n",
    "**Goal:**  Prepare a Bell state $|\\Phi^{+}\\rangle = \\frac{1}{\\sqrt{2}} (|00\\rangle + |11\\rangle)$ on these qubits."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%kata T1_CreateEntangledPair_Test\n",
    "\n",
    "operation CreateEntangledPair (q1 : Qubit, q2 : Qubit) : Unit is Adj {\n",
    "    // ...\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Task 2. Send the message (Alice's task) \n",
    "\n",
    "Encode the message (two classical bits) in the state of Alice's qubit.\n",
    "\n",
    "**Inputs**: \n",
    "1. Alice's part of the entangled pair of qubits qAlice.\n",
    "2. Two classical bits, stored as ProtocolMessage.\n",
    "\n",
    "**Goal**:  Transform the input qubit to encode the two classical bits.\n",
    "\n",
    ">`ProtocolMessage` is a custom type that represents the message to be transmitted. It includes two items of type `Bool` called `Bit1` and `Bit2`.\n",
    "\n",
    "<br/>\n",
    "<details>\n",
    "  <summary>Need a hint? Click here</summary>\n",
    "Manipulate Alice's half of the entangled pair to change the joint state of the two qubits to one of the following four states based on the value of message:   \n",
    "\n",
    "* [0; 0]: $|\\Phi^{+}\\rangle = \\frac{1}{\\sqrt{2}} (|00\\rangle + |11\\rangle)$\n",
    "* [0; 1]: $|\\Psi^{+}\\rangle = \\frac{1}{\\sqrt{2}} (|01\\rangle + |10\\rangle)$\n",
    "* [1; 0]: $|\\Phi^{-}\\rangle = \\frac{1}{\\sqrt{2}} (|00\\rangle - |11\\rangle)$\n",
    "* [1; 1]: $|\\Psi^{-}\\rangle = \\frac{1}{\\sqrt{2}} (|01\\rangle - |10\\rangle)$\n",
    "\n",
    "</details>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%kata T2_EncodeMessageInQubit_Test \n",
    "\n",
    "open Quantum.Kata.SuperdenseCoding;\n",
    "\n",
    "operation EncodeMessageInQubit (qAlice : Qubit, message : ProtocolMessage) : Unit {\n",
    "    if (message::Bit1) { // accesses the item 'Bit1' of 'message'\n",
    "        // ...\n",
    "    }\n",
    "    // ...\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Task 3. Decode the message and reset the qubits (Bob's task)\n",
    "\n",
    "Decode the message using the qubit received from Alice and reset both qubits to a $|00\\rangle$ state.\n",
    "\n",
    "**Inputs:**\n",
    "\n",
    "1. Qubit received from Alice qAlice.\n",
    "2. Bob's part of the entangled pair qBob.\n",
    "\n",
    "**Goal** :  Retrieve two bits of classic data from the qubits and return them as `ProtocolMessage`. The state of the qubits in the end of the operation should be $|00\\rangle$.\n",
    "\n",
    "> You can create an instance of `ProtocolMessage` as `ProtocolMessage(bit1value, bit2value)`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%kata T3_DecodeMessageFromQubits_Test \n",
    "\n",
    "open Quantum.Kata.SuperdenseCoding;\n",
    "\n",
    "operation DecodeMessageFromQubits (qAlice : Qubit, qBob : Qubit) : ProtocolMessage {\n",
    "    // ...\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Task 4. Superdense coding protocol end-to-end:\n",
    "\n",
    "Put together the steps performed in tasks 1-3 to implement the full superdense coding protocol.\n",
    "\n",
    "**Input:** Two classical bits to be transmitted.\n",
    "\n",
    "**Goal:**  Prepare an EPR Pair, encode the two classical bits in the state of the pair by applying quantum gates to one member of the pair, and decode the two classical bits from the state of the pair. Return the result of decoding."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%kata T4_SuperdenseCodingProtocol_Test\n",
    "\n",
    "open Quantum.Kata.SuperdenseCoding;\n",
    "\n",
    "operation SuperdenseCodingProtocol (message : ProtocolMessage) : ProtocolMessage {\n",
    "    // ...\n",
    "}"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Q#",
   "language": "qsharp",
   "name": "iqsharp"
  },
  "language_info": {
   "file_extension": ".qs",
   "mimetype": "text/x-qsharp",
   "name": "qsharp",
   "version": "0.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
